<template>
  <div class="department-container">
    <div class="app-container">
      <el-card>
        <!-- 用一个行列布局 -->
        <!-- el-row / el-col 属于布局容器 -->
        <el-row
          type="flex"
          justify="space-between"
          align="middle"
          style="height: 40px"
        >
          <el-col :span="20">
            <svg-icon icon-class="bank" /><span>江苏传智播客教育科技股份有限公司</span>
          </el-col>
          <el-col :span="4">
            <el-row type="flex" justify="end">
              <!-- 两个内容 -->
              <el-col>负责人</el-col>
              <!-- 下拉菜单 element -->
              <el-col>
                <el-dropdown>
                  <span> 操作<i class="el-icon-arrow-down" /> </span>
                  <el-dropdown-menu slot="dropdown">
                    <!-- 传入空的 id 就表示一级部门 -->
                    <el-dropdown-item
                      @click.native="hAddOrEdit('', false)"
                    >添加子部门</el-dropdown-item>
                  </el-dropdown-menu>
                </el-dropdown>
              </el-col>
            </el-row>
          </el-col>
        </el-row>

        <!-- 树形组件 -->
        <!-- default-expand-all: 默认展开所有子节点 -->
        <el-tree default-expand-all :data="list">
          <template v-slot="{ data }">
            <el-row
              type="flex"
              justify="space-between"
              align="middle"
              style="height: 40px; width: 100%"
            >
              <el-col :span="20">
                <span>{{ data.name }}</span>
              </el-col>
              <el-col :span="4">
                <el-row type="flex" justify="end">
                  <!-- 两个内容 -->
                  <el-col>{{ data.manager }}</el-col>
                  <!-- 下拉菜单 element -->
                  <el-col>
                    <el-dropdown>
                      <span> 操作<i class="el-icon-arrow-down" /> </span>
                      <el-dropdown-menu slot="dropdown">
                        <el-dropdown-item
                          @click.native="hAddOrEdit(data.id, false)"
                        >添加子部门</el-dropdown-item>
                        <el-dropdown-item
                          @click.native="hAddOrEdit(data.id, true)"
                        >编辑部门</el-dropdown-item>
                        <!-- 优化: 如果没有子部门就显示删除按钮 -->
                        <el-dropdown-item
                          v-if="data.children.length === 0"
                          @click.native="hDel(data.id)"
                        >删除部门</el-dropdown-item>
                      </el-dropdown-menu>
                    </el-dropdown>
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-tree>
      </el-card>
    </div>
    <el-dialog
      :title="dialogTitle"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :visible.sync="showDialog"
    >
      <!--
        烤串命名法: 常用于标签属性  Kebab-Case
        驼峰命名法: 常用于变量      Camel-Case
        这两种命名方式在组件使用 / Props 传值时可以互相替代使用
       -->

      <!-- 解决编辑部门数据不更新的问题: -->
      <!-- 方案1: v-if, 最推荐的方案, 没有之一 -->
      <!-- v-if 会在 DOM 上添加或删除, 如果用在组件上, 就会创建和销毁组件 -->
      <!-- v-if="showDialog" 将组件的生命周期和 dialog 的显示隐藏绑定 -->

      <!-- 方案2: $refs 调用子组件的方法发请求获取数据, 减少组件的创建和销毁, 提高性能 -->

      <!-- 方案3: 使用 watch 在子组件中侦听 id 的变化, 只要修改了就发请求获取最新的数据 -->

      <!--
        小结:
        方案1 (推荐使用): 用法简单, 贴合实际, Bug 最少, 会频繁创建销毁子组件
        方案2 / 3: 不会频繁创建销毁子组件, 但是需要额外处理其他的小 Bug, 例如: 编辑后再点添加
       -->
      <add-or-edit
        v-if="showDialog"
        :id="curId"
        ref="addOrEdit"
        :origin-list="originList"
        :is-edit="isEdit"
        @success="hSuccess"
        @close="hClose"
      />
    </el-dialog>
  </div>
</template>

<script>
import { getDepartments, delDepartment } from '@/api/departments'
import { tranListToTreeData } from '@/utils'
import AddOrEdit from './deptDialog.vue'

export default {
  components: {
    AddOrEdit
  },

  data() {
    return {
      list: [],
      showDialog: false,
      curId: '', // 当前被点击的部门 id
      isEdit: '',
      originList: []
      // list: [{
      //   name: '财务部',
      //   manager: '刘备',
      //   children: [
      //     {
      //       name: '财务核算部',
      //       manager: '张飞'
      //     },
      //     {
      //       name: '税务核算部',
      //       manager: '关羽'
      //     }
      //   ]
      // }]
      // list: [
      //   {
      //     label: '财务部',
      //     children: [
      //       {
      //         label: '财务核算部'
      //       },
      //       {
      //         label: '税务管理部'
      //       },
      //       {
      //         label: '薪资管理部'
      //       }
      //     ]
      //   }
      // ]
      // defaultProps: {
      //   children: 'children',
      //   label: 'name'
      // }
    }
  },
  // created() {
  //   // 路由信息对象, 存储 path / query / params
  //   console.log(this.$route.meta.title)
  // }

  computed: {
    dialogTitle() {
      return this.isEdit ? '编辑' : '添加'
    }
  },
  created() {
    this.loadDepartments()
  },
  methods: {
    // 1. 封装函数
    async loadDepartments() {
      // 2. try-catch 为了捕获异常, 减少网页中错误的出现
      try {
        const res = await getDepartments()
        // console.log(res.data.depts)
        // 任务: 复习数组的常用 API
        // shift: 删除数组的第一个元素, 返回删除的元素
        // pop: 删除数组的最后一个元素
        // push: 从末尾添加一个元素
        // unshift: 从开头添加一个元素
        // 四个方法都会直接修改原数组

        // 3. 删除获取到的数据中第一个元素 (传智教育)
        res.data.depts.shift()
        this.list = tranListToTreeData(res.data.depts)

        this.originList = res.data.depts.map((item) => {
          return {
            id: item.id,
            pid: item.pid,
            code: item.code,
            name: item.name
          }
        })

        // this.originList = res.data.depts.map(item =>
        //   ({ id: item.id, pid: item.pid, code: item.code, name: item.name })
        // )

        // {id, pid, code, name}: 等于把 item 的四个属性结构到当前作用域的局部变量
        // 非常优雅的代码, 不懂没关系
        // this.originList = res.data.depts.map(({ id, pid, code, name }) => ({ id, pid, code, name }))
        // this.list = res.data.depts.shift()
      } catch (e) {
        console.log('获取组织架构失败, 原因:', e)
      }
    },
    async hAddOrEdit(id, isEdit) {
      // 显示 dialog
      this.showDialog = true

      // 将当前点击的部门 id 传给子组件
      // console.log(id)
      this.curId = id

      // 当前在添加的逻辑
      this.isEdit = isEdit

      // // isEdit 为 true 表示用户点击了编辑
      // if (isEdit) {
      //   // DOM 更新是异步的 此时子组件还未创建
      //   // 需要等待下一次 DOM 更新完毕后再获取子组件
      //   this.$nextTick(() => {
      //     // 一般情况下不到万不得已, 不要随意调用子组件的函数, 容易导致维护困难
      //     // 回调函数就是下一次 DOM 更新完毕后自动执行的
      //     // 调用子组件的 loadDepartment 函数
      //     this.$refs.addOrEdit.loadDepartment()
      //   })

      //   // 以下代码完全等同于上面的回调
      //   // await this.$nextTick()
      //   // this.$refs.addOrEdit.loadDepartment()
      // }
    },
    hDel(id) {
      // console.log(data)
      // 1. 提示用户是否确定删除
      this.$confirm('确定删除吗?', '提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async() => {
          try {
            // 2. 当用户确定删除后发请求
            const res = await delDepartment(id)

            // 根据结果提醒用户
            this.$message.success(res.message)

            // 3. 重新获取组织架构
            this.loadDepartments()
          } catch (e) {
            this.$message.error(e.message)
          }
        })
        .catch((e) => {})
    },
    // hAdd(id) {
    //   // 显示 dialog
    //   this.showDialog = true

    //   // 将当前点击的部门 id 传给子组件
    //   // console.log(id)
    //   this.curId = id

    //   // 当前在添加的逻辑
    //   this.isEdit = false
    // },
    // hEdit(id) {
    //   // 显示 dialog
    //   this.showDialog = true
    //   // 将当前点击的部门 id 传给子组件
    //   // console.log(id)
    //   this.curId = id

    //   // 当前在编辑的逻辑
    //   this.isEdit = true
    // },
    hSuccess() {
      // 收到子组件通知的成功, 报喜
      // 关闭 dialog
      this.showDialog = false

      // 获取最新的数据
      this.loadDepartments()
    },
    hClose() {
      this.showDialog = false
    }
  }
}
</script>
